#define _GNU_SOURCE
#include "app_blt.h"

static unsigned char read_buff[1024]; // 蓝牙读取数据缓冲区
static int read_buff_len = 0;
static unsigned char fix_header[] = {0xf1, 0xdd};

/**
 * @brief 等待蓝牙应答
 * @param device 蓝牙设备
 */
static int wait_ack(Device_t *device)
{
    // 等待50ms
    usleep(1000 * 50);
    // 读取蓝牙数据
    char data[10] = {0};
    read(device->fd, data, 10);
    // 判断是否收到OK\r\n
    if (memcmp(data, "OK\r\n", 4) == 0)
    {
        return 0;
    }
    return -1;
}

int blt_test(Device_t *device)
{
    char *data = "AT\r\n";
    write(device->fd, data, 4);
    return wait_ack(device);
}

int blt_setName(Device_t *device, char *name)
{
    write(device->fd, "AT+NAME", 7);
    write(device->fd, name, strlen(name));
    write(device->fd, "\r\n", 2);
    return wait_ack(device);
}

static int blt_setBaudRate(Device_t *device, Blt_br_t blt_baudRate)
{
    if (blt_baudRate == BLT_BR_9600)
    {
        write(device->fd, "AT+BAUD4", 8);
        write(device->fd, "\r\n", 2);
    }
    else if (blt_baudRate == BLT_BR_115200)
    {
        write(device->fd, "AT+BAUD8", 8);
        write(device->fd, "\r\n", 2);
    }
    return wait_ack(device);
}

static int blt_reset(Device_t *device)
{
    write(device->fd, "AT+RESET", 8);
    write(device->fd, "\r\n", 2);
    return wait_ack(device);
}

int blt_setMADDR(Device_t *device,  char *maddr)
{
    write(device->fd, "AT+MADDR", 8);
    write(device->fd, maddr, 4);
    write(device->fd, "\r\n", 2);
    return wait_ack(device);
}

int blt_setNETID(Device_t *device,  char *netid)
{
    write(device->fd, "AT+NETID", 8);
    write(device->fd, netid, 4);
    write(device->fd, "\r\n", 2);
    int result = wait_ack(device);
    return result;
}

static int blt_init(Device_t *device)
{
    // 默认初始化为9600波特率
    int result = app_serial_init(device);
    if (result == 0)
    {
        // 初始化成功
        // 设置蓝牙芯片波特率
        blt_setBaudRate(device, BLT_BR_115200);
        // 重启蓝牙,更新数据
        blt_reset(device);
        log_debug("蓝牙重启成功");
        // 等待蓝牙复位
        sleep(1);
    }

    // 更新串口波特率
    app_serial_setBaudRate(device, BR_115200);
    tcflush(device->fd, TCIOFLUSH);

        // 测试更新波特率后，蓝牙是否可用
    if (blt_test(device) != 0)
    {
        log_error("blt test fail");
        return -1;
    }
    log_debug("修改波特率成功");
    // 设置蓝牙名称
    blt_setName(device, "zrc_blt");
    // 设置连接互通id
    blt_setNETID(device, "2227");
    // 设置蓝牙地址
    blt_setMADDR(device, "0965");
    // 重启蓝牙,更新数据
    blt_reset(device);
    // 等待蓝牙复位
    sleep(1);
    // 测试成功，串口设置为阻塞模式
    app_serial_setBlock(device, 1);
    tcflush(device->fd, TCIOFLUSH);
    return 0;
}

int app_blt_init(Device_t *device)
{
    // 设置处理读写格式转换回调函数
    device->post_read_task = app_blt_post_read_task;
    device->pre_write_task = app_blt_pre_write_task;

    return blt_init(device);
}

/*
    从蓝牙读取到数据后的处理 postRead
    接收方得到数据1（4）：ok\r\n
    接收方得到数据2（3 + [2]）：f1 dd 07 23 23 ff ff 41 42 43
        f1 dd : 固定的头部
        07： 之后数据的长度（5-16之间）
        23 23：对端（发送方）的MADDR
        ff ff: 我的MADDR或ffff(群发)
        41 42 43：发送的数据
    处理后的数据格式：conn_type id_len msg_len id msg
*/

int app_blt_post_read_task(char *data, int data_len)
{
    // 将读取到的数据拷贝到缓冲区
    memcpy(read_buff + read_buff_len, data, data_len);
    read_buff_len += data_len;

    if (read_buff_len < 4)
    {
        // 数据不完整
        return 0;
    }

    int i = 0;
    for (i = 0; i < read_buff_len - 7; i++)
    {
        // 从读取缓冲区中找到固定头部数据
        if (memcmp(read_buff + i, fix_header, 2) == 0)
        {
            // 找到数据,移动数据,将前i个字节丢弃
            memmove(read_buff, read_buff + i, read_buff_len - i);
            read_buff_len -= i;

            // 判断当前位置之后的数据长度是否合法
            if (read_buff[2] + 3 > read_buff_len)
            {
                // 数据不完整
                log_debug("数据长度不够");
                return 0;
            }

            memset(data, 0, data_len);
            // 拷贝数据到data
            // 连接类型
            data[0] = 1;
            // id_len
            data[1] = 2;
            // msg_len
            data[2] = read_buff[2] - 4;
            // 拷贝id
            memcpy(data + 3, read_buff + 3, 2);
            // msg
            memcpy(data + 5, read_buff + 7, data[2]);

            // 移除读取后的数据
            read_buff_len -= read_buff[2] + 3;
            memmove(read_buff, read_buff + read_buff[2] + 3, read_buff[2] + 3);
            return data[2] + 5; // 返回数据长度
        }
    }
    // 没有找到固定头部数据,丢弃数据
    memmove(read_buff, read_buff + i, read_buff_len - i);
    read_buff_len -= i;
    return 0;
}

/*
    字符数组消息:
       例子：1 2 3 XX abc
       格式：conn_type id_len msg_len id msg
    蓝牙发送数据格式例子：
        例子：41 54 2b 4d 45 53 48 00 ff ff 61 62 63 0d 0a
        41 54 2b 4d 45 53 48 00： AT+MESH\0（固定头部8个字节）
        ff ff: 对端的MADDR（如果是FFFF代表群发）
        61 62 63: 要发送的数据（不超过12字节）
        0d 0a：\r\n （固定结尾）
*/

int app_blt_pre_write_task(char *data, int data_len)
{
    // 判断数据长度是否小于6
    if (data_len < 6)
    {
        log_error("data len < 6");
        return -1;
    }
    int blt_len = 12 + data[2];
    char blt_buff[blt_len];
    // 拷贝AT+MESH到blt_buff
    memcpy(blt_buff, "AT+MESH", 8);
    // 拷贝id
    memcpy(blt_buff + 8, data + 3, 2);
    // 拷贝msg数据
    memcpy(blt_buff + 10, data + 5, data[2]);
    // 拷贝固定结尾
    memcpy(blt_buff + 10 + data[2], "\r\n", 2);

    // 清空传进来的data
    memset(data, 0, data_len);
    // 拷贝blt_buff到data
    memcpy(data, blt_buff, blt_len);

    // 返回写入AT命令的数据长度
    return blt_len;
}